package main

import (
	"context"
	"fmt"
	"gostu/tcp_server/frame"
	"gostu/tcp_server/packet"
	"net"
)

func main() {
	lis, err := net.Listen("tcp", ":8888")
	if nil != err {
		fmt.Println("listen error: ", err)
		return
	}
	fmt.Println("listening[ok] on :8888")

	for {
		ac, err := lis.Accept()
		if nil != err {
			fmt.Println("accpet error : ", ac, err)
			break
		}

		// 接收到连接信息，开始处理
		go handleConn(ac)
	}
}

// 处理连接传递的数据——frame
func handleConn(c net.Conn) {
	// Conn是监听fd，实现了IO接口
	defer c.Close()
	frameCode := frame.NewMyFrame()

	// 接收frame并处理完成后返回frame
	for {
		framePayload, err := frameCode.Decode(c) // []byte -> frame
		if nil != err {
			fmt.Println("handleConn: frame decode error: ", err)
			return
		}
		// 获取payload成功——如果遵守自定义的协议，那么这里得到framePayload是packet，如果不遵守，那么这里得到是乱码
		// 针对乱码的处理，则沉淀到packet中，如果发现不对，则返回错误
		ackFramePayload, err := handlePacket(framePayload)
		if nil != err {
			fmt.Println("handlePacket error:", err)
			return
		}
		// 应答frame再次发送
		// err = frame.Encode(c, ackFramePayload)
		err = frameCode.Encode(c, ackFramePayload)
		if nil != err {
			fmt.Println("handleConn: frame encode error:", err)
			return
		}

	}

}

// 处理数据包——packet
func handlePacket(fpayload frame.MyFramePayload) (frame.MyFramePayload, error) {
	// frame的payload解码
	var p packet.Packet

	// 总的packet包中解码入口
	p, err := packet.Decode(fpayload)
	if nil != err {
		fmt.Println("handlePacket: packet decode error:", err)
		return nil, err
	}

	// 解码出packet包——但是需要进一步确认是什么类型的包
	switch p.(type) {
	case *packet.Submit:
		ack, err := handleSubmit(context.Background(), p)
		if nil != err {
			fmt.Println("handleSubmit error:", err)
			return nil, err
		}
		// ackFramepayload, err := ack.Encode()  -- 这里出错导致的报错
		ackFramepayload, err := packet.Encode(ack)
		if nil != err {
			fmt.Println("handleSubmit ackpacket encode error:", err)
			return nil, err
		}
		return ackFramepayload, nil
	default:
		return nil, fmt.Errorf("unknow packet error")
	}
}

// 真实处理逻辑
/* 如果这样子传submit返回submitAck则表示开发者需要自己清楚ack的packet的结构，所以这个部分要不要屏蔽掉呢？ */
func handleSubmit(ctx context.Context, p packet.Packet) (packet.Packet, error) {
	submit, ok := p.(*packet.Submit)
	if !ok {
		fmt.Println("handleSubmit transform fail")
		return nil, fmt.Errorf("packet inteface transform fail")
	}
	fmt.Printf("server recv the submit data , id = %s , payload = %s \n", submit.ID, submit.Payload)

	// do ...
	// 处理完再响应

	ack := &packet.SubmitAck{
		ID:     submit.ID,
		Result: 0, // 响应0是协议规定的，表示成功
	}

	return ack, nil
}

// 这里就有一个问题了，究竟我要做到什么程度，要不要让接口实现者自己封包？
// 一般都是这下面做到封包——封包由框架完成，用户只需要关注好自己的业务，这里可以通过结构体完成或者直接使用[]byte作为传递
